package cc.lj.internal.coupons.domain.ticket.service.impl.deleteUseTicket;

import cc.lj.internal.core.exception.ServiceException;
import cc.lj.internal.coupons.domain.ticket.model.vo.TicketBatchDO;
import cc.lj.internal.coupons.domain.ticket.repository.IUseTicketCheckCacheRepository;
import cc.lj.internal.coupons.domain.ticket.service.IDeleteUseTicketDomainService;
import cc.lj.internal.coupons.domain.ticket.service.ITicketBatchDomainService;
import cc.lj.internal.coupons.domain.ticket.service.impl.useTicketRule.FindFirstStepUtil;
import cc.lj.internal.coupons.infrastructure.excepion.CoupousExceptionEnum;
import cc.lj.internal.coupons.interfaces.dto.command.DeleteUseTicketCheckCommand;
import lj.internal.dict.enums.redis.EnumUseTicketCheckRedisKeys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 删除用券 domain service impl
 * @author liangxifeng
 * @date 2023/6/30 16:36
 */
@Service("deleteUseTicketDomainServiceImpl")
@Slf4j
public class DeleteUseTicketDomainServiceImpl implements IDeleteUseTicketDomainService {
    //用券验证 redis 缓存仓储接口
    @Resource(name = "usetTicketCheckCacheRedisRepositoryImpl")
    private IUseTicketCheckCacheRepository cacheRepository;
    //查找每个阶梯中的第一张券 工具类
    @Resource(name = "findFirstStepUtil")
    private FindFirstStepUtil findFirstStepUtil;
    //电子券批次表 domain service
    @Resource(name = "ticketBatchDomainServiceImpl")
    private ITicketBatchDomainService ticketBatchDomainService;

    @Override
    public void deleteMain(TicketBatchDO ticketBatchDO, DeleteUseTicketCheckCommand checkCommand) {
        log.info("【取消用券domain】开始，电子券使用码:"+checkCommand.getTicketUseCode()+",command:"+checkCommand);
        //已用券redis 券列表 <券使用码,券批次主键>
        Map<String,Integer> usedRedisList = cacheRepository.getUseTicketList(checkCommand.getPactNum(),checkCommand.getUuId());
        if(usedRedisList.size() == 0 ) {
            log.error("取消用券domain：通过合同号："+checkCommand.getPactNum()+",uuId:"+checkCommand.getUuId()+"，在Redis中没有查询到已用券数据");
            throw new ServiceException(CoupousExceptionEnum.DELETE_USE_TICKET_REDIS_USELIST_IS_NULL);
        }
        //查询该券批次主键
        Integer batchId = usedRedisList.get(checkCommand.getTicketUseCode());
        if(batchId == null) {
            log.error("取消用券domain：通过使用码:"+checkCommand.getTicketUseCode()+",查询redis中已使用列表数据，没有查询到");
            throw new ServiceException(CoupousExceptionEnum.DELETE_USE_TICKET_REDIS_TICKET_IS_NULL);
        }
        //通过主键查询电子券批次信息
        ticketBatchDO = ticketBatchDomainService.getById(batchId);

        /**
         * 将该张券删除 redis 已用券列表，相关redis结构如下：
         * key1 = use_ticket_合同号_UUID (HASH), value1 = {券使用码:券批次主键} (删除以券使用码为hashKey的hash结构)
         * --------------------------------------------------------------
         * key2 = use_batch_合同号_UUID(HASH), value2 =  {券批次主键 : 使用张数} (-1操作)
         * --------------------------------------------------------------
         * key4 = global_used_券使用码_合同号_uuid(String 类型，目的：排除一张券在多个端用）,value = 券批次主键,(直接删除对应使用码key)
         * --------------------------------------------------------------
         * //key3 如果该批次券是独立使用券，那么删除对应 hashKey=single_batch_id, 阶梯第一张券 减少满减剩余额度 limit_value
         * key3 = batch_other_合同号_UUID (HASH), value = { single_batch_id: 独立使用的券批次主键, limit_value: 满减剩余额度空间)
         */
        //如果该券是 阶梯中的第一张券，则需要减小满减额度在redis中的值
        if( findFirstStepUtil.isStepFirstTicket(ticketBatchDO,checkCommand.getPactNum(),checkCommand.getUuId(),2) ) { //2 代表取消用券，1:代表用券

            //缓存中用券其他数据 <single_batch_id: 独立使用的券批次主键, limit_value: 满减剩余额度空间>
            Map<String,Object> useTicketOherData = cacheRepository.getUseTicketOther(checkCommand.getPactNum(),checkCommand.getUuId());
            //从redis中拿到满减剩余额度
            BigDecimal limitValue = new BigDecimal( useTicketOherData.get("limit_value").toString() );

            //新满减剩余空间 = 原满减剩余空间 + 此电子券占的额度
            BigDecimal newLimitValue = limitValue.add(ticketBatchDO.getConditionValue());
            Map<String,Object> limitValueMap = new HashMap<>();
            limitValueMap.put("limit_value",newLimitValue.toString());
            //设置 key3
            cacheRepository.setUseTicketOther(checkCommand.getPactNum(),checkCommand.getUuId(),limitValueMap);
            log.info("取消用券domain：该券是阶梯中的第一张券，redis中剩余额度空间设置成功，最新额度空间limit_value="+newLimitValue);
        }
        //撤销key1,key2,key4数据
        cacheRepository.deleteUseTicket(checkCommand);
        log.info("【取消用券domain】取消成功，电子券使用码:"+checkCommand.getTicketUseCode());
    }
}
